package com.lonely.system.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.lonely.common.core.domain.BaseEntity;
import com.lonely.common.core.domain.Cascader;
import com.lonely.common.core.domain.Select;
import com.lonely.system.domain.entity.SysUser;
import com.lonely.common.enums.DataScope;
import com.lonely.common.enums.UserStatus;
import com.lonely.common.threadlocals.DataPermissionThreadLocal;
import com.lonely.common.utils.SecurityUtils;
import com.lonely.system.domain.entity.SysFactory;
import com.lonely.system.domain.entity.SysProductionLine;
import com.lonely.system.domain.dto.factory.SysFactoryStatQueryDto;
import com.lonely.system.domain.dto.factory.SysFactorySubmitDto;
import com.lonely.system.domain.vo.system.factory.SplitOrderFactoryLineSelectVo;
import com.lonely.system.domain.vo.system.factory.SysFactoryStatsVo;
import com.lonely.system.enums.SysFactoryEnum;
import com.lonely.system.enums.SysProductionLineEnum;
import com.lonely.system.mapper.SysFactoryMapper;
import com.lonely.system.service.ISysFactoryService;
import com.lonely.system.service.ISysProductionLineService;
import com.lonely.system.service.ISysUserService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @author: 黄志标
 * @date: 2025/5/27 11:36
 * @description:
 */
@Service
public class SysFactoryServiceImpl extends ServiceImpl<SysFactoryMapper, SysFactory> implements ISysFactoryService {

    @Autowired
    private ISysUserService sysUserService;

    @Autowired
    private ISysProductionLineService sysProductionLineService;

    /**
     * 创建工厂
     *
     * @param companySubmitDto
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void create(SysFactorySubmitDto companySubmitDto) {
        Assert.isNull(companySubmitDto.getId(), "参数错误(id)");

        // 判断工厂名称是否已存在
        checkFactory(companySubmitDto);

        // 入库
        SysFactory sysFactory = new SysFactory();
        BeanUtils.copyProperties(companySubmitDto, sysFactory);
        sysFactory.setStatus(SysFactoryEnum.FactoryStatus.ENABLE.status);
        sysFactory.setCreateBy(SecurityUtils.getUserId());
        sysFactory.setUpdateBy(SecurityUtils.getUserId());
        super.save(sysFactory);
    }

    /**
     * 编辑公司
     *
     * @param companySubmitDto
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void edit(SysFactorySubmitDto companySubmitDto) {
        Assert.notNull(companySubmitDto.getId(), "参数错误(id)");

        // 判断工厂名称是否已存在
        checkFactory(companySubmitDto);

        SysFactory oldFactory = super.getById(companySubmitDto.getId());
        BeanUtils.copyProperties(companySubmitDto, oldFactory);
        oldFactory.setCreateBy(SecurityUtils.getUserId());
        oldFactory.setUpdateBy(SecurityUtils.getUserId());

        super.updateById(oldFactory);
    }

    /**
     * 工厂统计
     *
     * @param queryDto
     * @return
     */
    @Override
    public SysFactoryStatsVo stat(SysFactoryStatQueryDto queryDto) {

        // 获取工厂列表
        DataPermissionThreadLocal.setDataPermission(DataScope.FACTORY, "id");
        List<SysFactory> factorys = Optional.ofNullable(super.list(new LambdaQueryWrapper<SysFactory>()
                        .like(StrUtil.isNotBlank(queryDto.getFactoryName()), SysFactory::getName, queryDto.getFactoryName())
                        .in(CollUtil.isNotEmpty(queryDto.getStatus()), SysFactory::getStatus, queryDto.getStatus())))
                .orElse(new ArrayList<>());
        if (CollUtil.isEmpty(factorys)) {
            return null;
        }

        // 获取该工厂的用户信息
        DataPermissionThreadLocal.setDataPermission(DataScope.FACTORY, "factory_id");
        List<SysUser> users = this.sysUserService.list(new LambdaQueryWrapper<SysUser>().eq(SysUser::getStatus, UserStatus.ENABLED.getCode()));

        //根据工厂id进行分组
        Map<Long, Long> factoryUserNumMap = new HashMap<>();
        if (CollUtil.isNotEmpty(users)) {
            factoryUserNumMap.putAll(users.stream().collect(Collectors.groupingBy(SysUser::getFactoryId, Collectors.counting())));
        }

        // 根据类型进行分组
        List<SysFactoryStatsVo.SysFactoryStatVo> factoryStats = factorys.stream()
                .map(factory -> {
                    SysFactoryStatsVo.SysFactoryStatVo factoryStatVo = new SysFactoryStatsVo.SysFactoryStatVo();
                    factoryStatVo.setId(factory.getId());
                    factoryStatVo.setName(factory.getName());
                    factoryStatVo.setType(factory.getType());
                    factoryStatVo.setEmployeeNum(Convert.toInt(MapUtil.getLong(factoryUserNumMap, factory.getId(), 0L)));
                    factoryStatVo.setStatus(factory.getStatus());
                    return factoryStatVo;
                }).collect(Collectors.toList());

        List<SysFactoryStatsVo.SysFactoryStatVo> ownFactoryStats = factoryStats.stream().filter(factory -> Objects.equals(factory.getType(), SysFactoryEnum.FactoryType.OWN.type)).collect(Collectors.toList());
        List<SysFactoryStatsVo.SysFactoryStatVo> cooperativeFactoryStats = factoryStats.stream().filter(factory -> Objects.equals(factory.getType(), SysFactoryEnum.FactoryType.COOPERATIVE.type)).collect(Collectors.toList());

        SysFactoryStatsVo factoryStatsVo = new SysFactoryStatsVo();
        factoryStatsVo.setTotalFactoryNum(factoryStats.size());
        factoryStatsVo.setTotalOwnFactoryNum(ownFactoryStats.size());
        factoryStatsVo.setTotalOwnFactoryEmployeeNum(ownFactoryStats.stream().mapToInt(SysFactoryStatsVo.SysFactoryStatVo::getEmployeeNum).sum());
        factoryStatsVo.setTotalCooperativeFactoryNum(cooperativeFactoryStats.size());
        factoryStatsVo.setTotalCooperativeFactoryEmployeeNum(cooperativeFactoryStats.stream().mapToInt(SysFactoryStatsVo.SysFactoryStatVo::getEmployeeNum).sum());
        factoryStatsVo.setOwnFactorys(ownFactoryStats);
        factoryStatsVo.setCooperativeFactorys(cooperativeFactoryStats);
        return factoryStatsVo;
    }

    /**
     * 暂停工厂分单
     *
     * @param factoryId
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void suspendSplitOrders(Long factoryId) {
        super.update(new LambdaUpdateWrapper<SysFactory>()
                .eq(SysFactory::getId, factoryId)
                .set(SysFactory::getStatus, SysFactoryEnum.FactoryStatus.SUSPEND_SPLIT_ORDERS.status)
                .set(SysFactory::getUpdateBy, SecurityUtils.getUserId())
        );
    }

    /**
     * 停用工厂
     *
     * @param factoryId
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void stopUsing(Long factoryId) {
        super.update(new LambdaUpdateWrapper<SysFactory>()
                .eq(SysFactory::getId, factoryId)
                .set(SysFactory::getStatus, SysFactoryEnum.FactoryStatus.DISABLE.status)
                .set(SysFactory::getUpdateBy, SecurityUtils.getUserId())
        );
    }

    /**
     * 获取工厂下拉列表
     *
     * @return
     */
    @Override
    public List<Select> getFactorySelectOptions() {
        DataPermissionThreadLocal.setDataPermission(DataScope.FACTORY, "id");
        return super.list(new LambdaQueryWrapper<SysFactory>().eq(SysFactory::getStatus, SysFactoryEnum.FactoryStatus.ENABLE.status))
                .stream().map(x -> new Select().setLabel(x.getName()).setValue(String.valueOf(x.getId()))).collect(Collectors.toList());
    }

    /**
     * 获取分单时候的工厂线路选择列表
     *
     * @return
     */
    @Override
    public SplitOrderFactoryLineSelectVo getSplitOrderFactoryLineSelectOptions() {

        List<SysFactory> factories = super.list(new LambdaQueryWrapper<SysFactory>().eq(SysFactory::getStatus, SysFactoryEnum.FactoryStatus.ENABLE.status));

        if (CollUtil.isEmpty(factories)) {
            return null;
        }

        List<Long> factoryIds = factories.stream().map(BaseEntity::getId).distinct().collect(Collectors.toList());
        Map<Long, List<SysProductionLine>> lineMap = this.sysProductionLineService.list(new LambdaQueryWrapper<SysProductionLine>().in(SysProductionLine::getFactoryId, factoryIds)
                        .eq(SysProductionLine::getStatus, SysProductionLineEnum.ProductionLineStatus.ENABLE.status)).stream()
                .collect(Collectors.groupingBy(SysProductionLine::getFactoryId));

        List<SplitOrderFactoryLineSelectVo.FactorySelectVo> factorySelectVos = new ArrayList<>();
        for (SysFactory factory : factories) {
            SplitOrderFactoryLineSelectVo.FactorySelectVo factorySelectVo = new SplitOrderFactoryLineSelectVo.FactorySelectVo();
            factorySelectVo.setLabel(factory.getName());
            factorySelectVo.setValue(factory.getId());
            factorySelectVo.setType(factory.getType());

            List<Cascader> children = new ArrayList<>();
            if (lineMap.containsKey(factory.getId())) {
                List<SysProductionLine> currentLines = lineMap.get(factory.getId());
                if (CollUtil.isNotEmpty(currentLines)) {
                    for (SysProductionLine currentLine : currentLines) {
                        Cascader currentCas = new Cascader();
                        currentCas.setLabel(currentLine.getName());
                        currentCas.setValue(currentLine.getId());
                        children.add(currentCas);
                    }
                }
            }
            factorySelectVo.setChildren(children);
            factorySelectVos.add(factorySelectVo);
        }

        // 提取自有分厂
        List<SplitOrderFactoryLineSelectVo.FactorySelectVo> ownFactorys = factorySelectVos.stream().filter(x -> Objects.equals(x.getType(), SysFactoryEnum.FactoryType.OWN.type)).collect(Collectors.toList());

        // 提取合作分厂
        List<SplitOrderFactoryLineSelectVo.FactorySelectVo> cooperativeFactorys = factorySelectVos.stream().filter(x -> Objects.equals(x.getType(), SysFactoryEnum.FactoryType.COOPERATIVE.type)).collect(Collectors.toList());

        return new SplitOrderFactoryLineSelectVo()
                .setCooperativeFactorys(cooperativeFactorys)
                .setOwnFactorys(ownFactorys);
    }

    /**
     * 根据工厂id获取供应名称
     *
     * @param factoryId
     * @return
     */
    @Override
    public String getFactoryName(Long factoryId) {
        SysFactory factory = super.getById(factoryId);
        Assert.notNull(factory, "工厂不存在");
        return factory.getName();
    }


    /**
     * 校验工厂信息
     *
     * @param companySubmitDto
     */
    private void checkFactory(SysFactorySubmitDto companySubmitDto) {

        //1. 校验工厂是否已存在
        int count = super.count(new LambdaQueryWrapper<SysFactory>().eq(SysFactory::getName, companySubmitDto.getName())
                .eq(SysFactory::getType, companySubmitDto.getType())
                .ne(companySubmitDto.getId() != null, SysFactory::getId, companySubmitDto.getId()));
        Assert.isTrue(count == 0, "该工厂已存在");

        //2. 检验工厂id对应的数据是否存在
        if (companySubmitDto.getId() != null) {
            SysFactory oldFactory = super.getById(companySubmitDto.getId());
            Assert.notNull(oldFactory, "工厂不存在");
        }
    }


}
